package com.soxing.webrain.brush.controller;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.soxing.webrain.brush.common.util.BigFileUtil;
import com.soxing.webrain.brush.common.util.PageUtils;
import com.soxing.webrain.brush.dao.entity.Algorithm;
import com.soxing.webrain.brush.dao.entity.Paradigm;
import com.soxing.webrain.brush.dao.entity.User;
import com.soxing.webrain.brush.dao.mapper.TaskMapper;
import com.soxing.webrain.brush.dao.service.impl.AlgorithmServiceImpl;
import com.soxing.webrain.brush.dao.service.impl.ParadigmServiceImpl;
import com.soxing.webrain.brush.dao.service.impl.TaskServiceImpl;
import com.soxing.webrain.brush.service.docker.MyDockerClient;
import com.soxing.webrain.brush.service.work.MyTaskExecutor;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import com.soxing.webrain.brush.dao.entity.Task;
import com.soxing.webrain.brush.domain.view.R;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 被试信息
 *
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2024-04-02 10:02:28
 */
@RestController
@RequestMapping("/task")
public class TaskController {
    @Resource
    private TaskServiceImpl taskService;

    @Resource
    private MyTaskExecutor myTaskExecutor;

    @Resource
    private ParadigmServiceImpl paradigmService;

    @Resource
    private AlgorithmServiceImpl algorithmService;

    @Resource
    private MyDockerClient dockerClient;

    @Value("${feedback.mountPath}")
    String mountPath;
    @Value("${feedback.inputPath}")
    String inputPath;
    @Value("${feedback.outputPath}")
    String outputPath;
    @Value("${feedback.zipPath}")
    String zipPath;

    /**
     * 列表
     */
    @RequestMapping("/list")
    public R list(@RequestParam Map<String, Object> params){
        PageUtils page = taskService.queryPage(params);

        return R.ok().data("page", page);
    }

    @RequestMapping("/getListByTesteeId")
    public R getListByTesteeId(@RequestParam Integer id){
        List<Task> taskList = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getTesteeId,id).orderByDesc(Task::getId));

        return R.ok().data("list", taskList);
    }


    /**
     * 信息
     */
    @RequestMapping("/info/{id}")
    public R info(@PathVariable("id") Long id){
        Task task = taskService.getById(id);

        return R.ok().data("task", task);
    }

    /**
     * 保存
     */
    @RequestMapping("/save")
    public R save(@RequestBody Task task){
        taskService.save(task);

        return R.ok().data("data", task);
    }

    /**
     * 修改
     */
    @RequestMapping("/update")
    public R update(@RequestBody Task task){
        taskService.updateById(task);

        return R.ok();
    }

    /**
     * 删除
     */
    // TODO 删除task的时候要不要把文件也删了🤔
    @RequestMapping("/delete")
    public R delete(@RequestParam Integer id){
        taskService.removeById(id);

        return R.ok();
    }

    @RequestMapping("/startTask")
    public R startTask(@RequestBody Task task) throws Exception {
        if ( task.getParadigmId() != null && task.getTesteeId() != null ) {
            task.setName(Long.toString(System.currentTimeMillis()));
            task.setCreateTime(new Date());
            task.setStatus(0);
            Paradigm paradigm = paradigmService.getById(task.getParadigmId());
            if(paradigm.getAlgorithmId() == null) {
                return R.error().message("该实验范式未设置计算镜像，启动失败");
            }
            Algorithm algorithm = algorithmService.getById(paradigm.getAlgorithmId());
            String image = algorithm.getImage();

            taskService.save(task);
            task.setInput(inputPath + task.getId());
            task.setOutput(outputPath + task.getId());
            task.setMountPath(mountPath);

            // 任务状态 -1:信息不完整  0:未开始  1:训练中 2:终止训练 3:等待评估 6:评估中4:评估成功 5:执行失败
            Map<String, Object> params = new HashMap<>();
            params.put("status", 1);
            List<Task> executingProjectList = taskService.listByMap(params);
            if (executingProjectList.size() > 0) {
                return  R.error().message("有正在进行或未正常结束的训练任务,启动失败,请点击下方[初始化容器]后重试");
            }

            // 启动容器
            String containerId = myTaskExecutor.execute(task, image);
            task.setContainerId(containerId);
            task.setStatus(1);
            taskService.updateById(task);
        } else {
            return R.error().message("开始训练失败");
        }
        return R.ok().data("data", task);
    }

    @RequestMapping("/stopTask")
    public R stopTask(@RequestBody Task task) {
        myTaskExecutor.stopTask(task);
        return R.ok().data("data", task);
    }

    @RequestMapping("/leaveTask")
    public R leaveTask(@RequestBody Task task) {
        myTaskExecutor.leaveTask(task);
        return R.ok();
    }

    @RequestMapping("/initAllContainer")
    public R initAllContainer() {
        try {
            List<Paradigm> paradigmList = paradigmService.list();
            List<Algorithm> algorithmList = new ArrayList<>();
            Set matchedFields = new HashSet<>();

            for (Paradigm paradigm : paradigmList) {
                Integer algorithmId = paradigm.getAlgorithmId();
                if (algorithmId != null) {
                    if(!matchedFields.contains(algorithmId)) {
                        algorithmList.add(algorithmService.getById(algorithmId));
                        matchedFields.add(algorithmId);
                    }
                }
            }

            for (Algorithm algorithm : algorithmList) {
                String image = algorithm.getImage();
<<<<<<< HEAD
                Boolean flag = dockerClient.clearContainers(image);
                if(!flag) {
                    return R.error().message("初始化容器失败");
=======
                // 查找正在运行的容器
                ProcessBuilder processBuilder = new ProcessBuilder("docker", "ps", "-q", "--filter", "ancestor=" + image);
                Process process = processBuilder.start();

                // 读取输出
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        if (!line.trim().isEmpty()) {
                            // 停止容器
                            stopContainerById(line.trim());
                        }
                    }
                }
                // 等待命令执行完成
                int exitCode = process.waitFor();
                if (exitCode != 0) {
                    System.err.println("Failed to find containers with image " + image);
>>>>>>> origin/develop
                }
            }

            List<Task> taskList = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getStatus, 1));
            for(Task task : taskList) {
                task.setStatus(2);
                taskService.updateById(task);
            }
            return R.ok();
        } catch (Exception e) {
            return R.error().message(e.getMessage());
        }
    }

<<<<<<< HEAD
=======
    private static void stopContainerById(String containerId) throws IOException, InterruptedException {
        ProcessBuilder stopProcessBuilder = new ProcessBuilder("docker", "stop", containerId);
        Process stopProcess = stopProcessBuilder.start();
        int exitCode = stopProcess.waitFor();
        if (exitCode == 0) {
            System.out.println("Container with ID " + containerId + " has been stopped.");
        } else {
            System.err.println("Failed to stop container with ID " + containerId);
        }
    }

>>>>>>> origin/develop
    @RequestMapping("/zipFile")
    public R zipFile(@RequestBody Task task) {
        try {
            String inputPath = task.getMountPath() + "data/" + task.getId();
            String outputPath = zipPath + task.getId() + "/" + task.getTesteeId() + "-" + task.getId() + "-EEG.zip";
            String outputFolder = zipPath + task.getId();
            File zipFolder = new File(outputFolder);
            if (!zipFolder.exists()) {
                zipFolder.mkdirs();
            }
            File oldZipFile = new File(outputPath);
            if(oldZipFile.exists()) {
                return R.ok().data("path", outputPath);
            } else {
                BigFileUtil.ZipCompress(inputPath, outputPath);
//                BigFileUtil.ZipCompress("/export/feedback/data/73","/export/feedback/zip/73/32-73-EEG.zip");
                File zipFile = new File(outputPath);
                if(!zipFile.exists()) {
                    return R.error().message("压缩数据文件失败");
                }
            }
            return R.ok().data("path", outputPath);
        } catch (Exception e) {
            return R.error().message(e.getMessage());
        }
    }

    @GetMapping("/downloadFile")
    @ApiOperation(value = "下载文件")
    public void downloadFile(HttpServletRequest request, HttpServletResponse response,@RequestParam String filePath) throws IOException {
        File a = new File(filePath);
        BigFileUtil.downloadBigFile(request,response,a);
    }

}
